﻿using Core.Caching;
using Core.Pipeline.Attributes;
using Finbuckle.MultiTenant.Abstractions;
using Infrastructure.Tenant;
using MediatR;
using Microsoft.Extensions.Logging;
using ZiggyCreatures.Caching.Fusion;

namespace Infrastructure.Pipeline;

/// <summary>
/// 添加缓存
/// </summary>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TResponse"></typeparam>
[PipelineOrder(1)]
public class CacheBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : ICacheableRequest<TResponse>
{
    private readonly IFusionCache _cache;
    private readonly ILogger<CacheBehaviour<TRequest, TResponse>> _logger;
    private readonly IMultiTenantContextAccessor<BoilerplateTenantInfo> _multiTenantContextAccessor;

    public CacheBehaviour(
        IFusionCache cache,
        ILogger<CacheBehaviour<TRequest, TResponse>> logger,
        IMultiTenantContextAccessor<BoilerplateTenantInfo> multiTenantContextAccessor
        )
    {
        _cache = cache;
        _logger = logger;
        _multiTenantContextAccessor = multiTenantContextAccessor;
    }
    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
    {
        var cacheProxy = _multiTenantContextAccessor.MultiTenantContext.TenantInfo?.Id!;
        _logger.LogDebug("{Name} 正在缓存 {@Request}", nameof(request), request);
        var response = await _cache.GetOrSetAsync(
           request.CacheKey.GetCacheKey(cacheProxy),
            _ => next(),
            tags: request.Tags!.GetCacheTags(cacheProxy)
            ).ConfigureAwait(false);

        return response;
    }
}
